package com.kuaimacode.kframework.util;

import org.apache.commons.lang3.time.DateUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.text.DateFormat;
import java.text.ParseException;
import java.text.ParsePosition;
import java.text.SimpleDateFormat;
import java.time.*;
import java.time.temporal.ChronoUnit;
import java.util.*;
import java.util.regex.Pattern;
import java.util.stream.Stream;

/**
 * @author qinyong
 * @Title:
 * @Package com.daikuan.platform.message.util
 * @Description: created by IntelliJ IDEA
 * @date 2019-03-01 17:27
 */
public class DateUtil {

    private static final Logger LOGGER = LoggerFactory.getLogger(DateUtil.class);

    private DateUtil() {
        throw new IllegalStateException("Utility class");
    }

    public static final String DATE_FORMATE_STRING_A = "yyyy-MM-dd HH:mm:ss";

    // 格式：年－月－日 小时：分钟：秒
    public static final String FORMAT_ONE = "yyyy-MM-dd HH:mm:ss";

    // 格式：年－月－日 小时：分钟
    public static final String FORMAT_TWO = "yyyy-MM-dd HH:mm";

    // 格式：年月日 小时分钟秒
    public static final String FORMAT_THREE = "yyyyMMdd-HHmmss";

    // 格式：年月日
    public static final String FORMAT_FOUR = "yyyyMMdd";

    // 格式：年月日时分秒
    public static final String FORMAT_FOUR_MINUTE = "yyyyMMddHHmmss";

    // 格式：年－月－日
    public static final String LONG_DATE_FORMAT = "yyyy-MM-dd";

    // 格式：月－日
    public static final String SHORT_DATE_FORMAT = "MM-dd";

    // 格式：小时：分钟：秒
    public static final String LONG_TIME_FORMAT = "HH:mm:ss";

    //格式：年-月
    public static final String MONTG_DATE_FORMAT = "yyyy-MM";

    // 年的加减
    public static final int SUB_YEAR = Calendar.YEAR;

    // 月加减
    public static final int SUB_MONTH = Calendar.MONTH;

    // 天的加减
    public static final int SUB_DAY = Calendar.DATE;

    // 小时的加减
    public static final int SUB_HOUR = Calendar.HOUR;

    // 分钟的加减
    public static final int SUB_MINUTE = Calendar.MINUTE;

    // 秒的加减
    public static final int SUB_SECOND = Calendar.SECOND;

    static final String dayNames[] = {"星期日", "星期一", "星期二", "星期三", "星期四",
            "星期五", "星期六"};

    /**
     * 根据类型加减时间
     *
     * @param dateEnum
     * @param toAdd
     * @return
     */
    public static Date plus(DateEnum dateEnum, long toAdd) {
        LocalDateTime localDateTime = LocalDateTime.now();
        switch (dateEnum) {
            case YEAR:
                localDateTime = localDateTime.plusYears(toAdd);
                break;
            case MONTH:
                localDateTime = localDateTime.plusMonths(toAdd);
                break;
            case DAY:
                localDateTime = localDateTime.plusDays(toAdd);
                break;
            case HOUR:
                localDateTime = localDateTime.plusHours(toAdd);
                break;
            case MINUTE:
                localDateTime = localDateTime.plusMinutes(toAdd);
                break;
            case SECONDS:
                localDateTime = localDateTime.plusSeconds(toAdd);
                break;
            default:
        }
        return localDateTime2Date(localDateTime);
    }

    public static Date plus(Date date, DateEnum dateEnum, int toAdd) {
        Calendar c = Calendar.getInstance();
        c.setTime(date);
        switch (dateEnum) {
            case YEAR:
                c.add(Calendar.YEAR, toAdd);
                break;
            case MONTH:
                c.add(Calendar.MONTH, toAdd);
                break;
            case DAY:
                c.add(Calendar.DAY_OF_MONTH, toAdd);
                break;
            case HOUR:
                c.add(Calendar.HOUR_OF_DAY, toAdd);
                break;
            case MINUTE:
                c.add(Calendar.MINUTE, toAdd);
                break;
            case SECONDS:
                c.add(Calendar.SECOND, toAdd);
                break;
            default:
        }
        return c.getTime();
    }

    /**
     * 获取当前时间
     *
     * @return
     */
    public static Date now() {
        return new Date();
    }

    public static String format(Date date, String format) {
        SimpleDateFormat dateFormat = new SimpleDateFormat(format);
        return dateFormat.format(date);
    }

    public static String format(Date date) {
        return DateUtil.format(date, DateUtil.DATE_FORMATE_STRING_A);
    }

    public static String format() {
        return DateUtil.format(new Date(), DateUtil.DATE_FORMATE_STRING_A);
    }

    /**
     * 将localDateTime转为date
     *
     * @param localDateTime
     * @return
     */
    public static Date localDateTime2Date(LocalDateTime localDateTime) {
        if (null == localDateTime) {
            return null;
        }
        ZonedDateTime zonedDateTime = localDateTime.atZone(ZoneId.systemDefault());
        return Date.from(zonedDateTime.toInstant());
    }

    /**
     * 将Date转为LocalDateTime
     *
     * @param date
     * @return
     */
    public static LocalDateTime date2LocalDateTime1(Date date) {
        if (null == date) {
            return null;
        }
        return LocalDateTime.ofInstant(date.toInstant(), ZoneId.systemDefault());
    }

    public enum DateEnum {
        /**
         *
         */
        YEAR, MONTH, DAY, HOUR, MINUTE, SECONDS
    }


    /**
     * 把符合日期格式的字符串转换为日期类型
     */
    public static Date stringtoDate(String dateStr, String format) {
        Date d = null;
        SimpleDateFormat formater = new SimpleDateFormat(format);
        try {
            formater.setLenient(false);
            d = formater.parse(dateStr);
        } catch (Exception e) {
            // log.error(e);
            d = null;
        }
        return d;
    }

    /**
     * 把符合日期格式的字符串转换为日期类型
     */
    public static Date stringtoDate(String dateStr, String format,
                                    ParsePosition pos) {
        Date d = null;
        SimpleDateFormat formater = new SimpleDateFormat(format);
        try {
            formater.setLenient(false);
            d = formater.parse(dateStr, pos);
        } catch (Exception e) {
            d = null;
        }
        return d;
    }

    /**
     * 把日期转换为字符串
     */
    public static String dateToString(Date date, String format) {
        String result = "";
        SimpleDateFormat formater = new SimpleDateFormat(format);
        try {
            result = formater.format(date);
        } catch (Exception e) {
            // log.error(e);
        }
        return result;
    }

    /**
     * 获取当前时间的指定格式
     */
    public static String getCurrDate(String format) {
        return dateToString(new Date(), format);
    }

    /**
     * @throws
     * @Title: dateSub
     * @Date 2014-1-9 上午10:44:02
     * @Description: 得到指定日期前(后)的日期
     * @param: @param dateKind  例：Calendar.DAY_OF_MONTH
     * @param: @param dateStr  指定日期
     * @param: @param amount   增加(减去)的时间量
     * @param: @return
     * @return: String
     * @author mtf
     */
    public static String dateSub(int dateKind, String dateStr, int amount) {
        Date date = stringtoDate(dateStr, MONTG_DATE_FORMAT);
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.add(dateKind, amount);
        return dateToString(calendar.getTime(), FORMAT_ONE);
    }

    /**
     * @throws
     * @Title: dateSub
     * @Date 2014-1-9 上午10:44:02
     * @Description: 得到指定日期前(后)的日期
     * @param: @param dateKind  例：Calendar.DAY_OF_MONTH
     * @param: @param dateStr  指定日期
     * @param: @param amount   增加(减去)的时间量
     * @param: @return
     * @return: String
     * @author mtf
     */
    public static String dateSub(int dateKind, int amount, String format) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(new Date());
        calendar.add(dateKind, amount);
        return dateToString(calendar.getTime(), format);
    }

    /**
     * 昨日日期
     *
     * @return
     */
    public static String yearthDate(String dateStr) {
        Date date = stringtoDate(dateStr, LONG_DATE_FORMAT);//取时间
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.add(calendar.DATE, -1);//把日期往后增加一天.整数往后推,负数往前移动
        //date=calendar.getTime();   //这个时间就是日期往后推一天的结果
        return dateToString(calendar.getTime(), LONG_DATE_FORMAT);
    }

    /**
     * 两个日期相减
     *
     * @return 相减得到的秒数
     */
    public static long timeSub(String firstTime, String secTime) {
        long first = stringtoDate(firstTime, FORMAT_ONE).getTime();
        long second = stringtoDate(secTime, FORMAT_ONE).getTime();
        return (second - first) / 1000;
    }

    /**
     * 两个日期相减
     *
     * @return 相减得到的秒数
     */
    public static long timeSubSec(Date firstTime, Date secTime) {
        long first = firstTime.getTime();
        long second = secTime.getTime();
        return (second - first) / 1000;
    }

    /**
     * 两个日期相减
     * 参数地DATE
     * second 两个日期相差的秒
     *
     * @return 相减得到的秒数
     * 后面时间减去前面时间  再减去 相差秒数    如果大于0 返回 FASLE
     */
    public static boolean timeSub(Date firstTime, Date secTime, long secs) {
        long first = firstTime.getTime();
        long second = secTime.getTime();
        // 判断两个时间 是否间隔那么长 secs。
        return (second - first - secs) > 0 ? false : true;
    }

    /**
     * 两个日期相减
     * 参数地DATE
     *
     * @return 相减得到的秒数
     * 后面时间减去前面时间  如果大于0 返回 false
     */
    public static boolean timeSub(Date firstTime, Date secTime) {
        long first = firstTime.getTime();
        long second = secTime.getTime();
        return (second - first) > 0 ? false : true;
    }

    /**
     * 两个日期相减
     * 参数地DATE
     *
     * @return 相减得到的分钟数
     * 后面时间减去前面时间 =
     */
    public static Long timeSubMin(Date firstTime, Date secTime) {
        long first = firstTime.getTime();
        long second = secTime.getTime();
        return (second - first) / 1000 / 60;
    }

    /**
     * 获得某月的天数
     */
    public static int getDaysOfMonth(String year, String month) {
        int days = 0;
        if (month.equals("1") || month.equals("3") || month.equals("5")
                || month.equals("7") || month.equals("8") || month.equals("10")
                || month.equals("12")) {
            days = 31;
        } else if (month.equals("4") || month.equals("6") || month.equals("9")
                || month.equals("11")) {
            days = 30;
        } else {
            if ((Integer.parseInt(year) % 4 == 0 && Integer.parseInt(year) % 100 != 0)
                    || Integer.parseInt(year) % 400 == 0) {
                days = 29;
            } else {
                days = 28;
            }
        }

        return days;
    }

    /**
     * 获取某年某月的天数
     */
    public static int getDaysOfMonth(int year, int month) {
        Calendar calendar = Calendar.getInstance();
        calendar.set(year, month - 1, 1);
        return calendar.getActualMaximum(Calendar.DAY_OF_MONTH);
    }

    /**
     * 获得当前日期
     */
    public static int getToday() {
        Calendar calendar = Calendar.getInstance();
        return calendar.get(Calendar.DATE);
    }

    /**
     * 获得当前月份
     */
    public static int getToMonth() {
        Calendar calendar = Calendar.getInstance();
        return calendar.get(Calendar.MONTH) + 1;
    }

    /**
     * 获得当前年份
     */
    public static int getToYear() {
        Calendar calendar = Calendar.getInstance();
        return calendar.get(Calendar.YEAR);
    }

    /**
     * 返回日期的天
     */
    public static int getDay(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        return calendar.get(Calendar.DATE);
    }

    /**
     * 返回日期的年
     */
    public static int getYear(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        return calendar.get(Calendar.YEAR);
    }

    /**
     * 返回日期的月份，1-12
     */
    public static int getMonth(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        return calendar.get(Calendar.MONTH) + 1;
    }

    /**
     * 计算两个日期相差的天数，如果date2 > date1 返回正数，否则返回负数
     */
    public static long dayDiff(Date date1, Date date2) {
        return (date2.getTime() - date1.getTime()) / 86400000;
    }


    /**
     * 比较两个日期的年差
     */
    public static int yearDiff(String before, String after) {
        Date beforeDay = stringtoDate(before, LONG_DATE_FORMAT);
        Date afterDay = stringtoDate(after, LONG_DATE_FORMAT);
        return getYear(afterDay) - getYear(beforeDay);
    }

    /**
     * 比较指定日期与当前日期的差
     */
    public static int yearDiffCurr(String after) {
        Date beforeDay = new Date();
        Date afterDay = stringtoDate(after, LONG_DATE_FORMAT);
        return getYear(beforeDay) - getYear(afterDay);
    }

    /**
     * 获取每月的第一周
     */
    public static int getFirstWeekdayOfMonth(int year, int month) {
        Calendar c = Calendar.getInstance();
        c.setFirstDayOfWeek(Calendar.SATURDAY); // 星期天为第一天
        c.set(year, month - 1, 1);
        return c.get(Calendar.DAY_OF_WEEK);
    }

    /**
     * 获取每月的最后一周
     */
    public static int getLastWeekdayOfMonth(int year, int month) {
        Calendar c = Calendar.getInstance();
        c.setFirstDayOfWeek(Calendar.SATURDAY); // 星期天为第一天
        c.set(year, month - 1, getDaysOfMonth(year, month));
        return c.get(Calendar.DAY_OF_WEEK);
    }

    /**
     * 获得当前日期字符串，格式"yyyy-MM-dd HH:mm:ss"
     *
     * @return
     */
    public static String getNow() {
        return getNow(FORMAT_ONE);
    }

    /**
     * 获得当前日期字符串，指定格式
     *
     * @return
     */
    public static String getNow(String format) {
        Calendar today = Calendar.getInstance();
        return dateToString(today.getTime(), format);
    }


    /**
     * 判断日期是否有效,包括闰年的情况
     *
     * @param date YYYY-mm-dd
     * @return
     */
    public static boolean isDate(String date) {
        StringBuffer reg = new StringBuffer(
                "^((\\d{2}(([02468][048])|([13579][26]))-?((((0?");
        reg.append("[13578])|(1[02]))-?((0?[1-9])|([1-2][0-9])|(3[01])))");
        reg.append("|(((0?[469])|(11))-?((0?[1-9])|([1-2][0-9])|(30)))|");
        reg.append("(0?2-?((0?[1-9])|([1-2][0-9])))))|(\\d{2}(([02468][12");
        reg.append("35679])|([13579][01345789]))-?((((0?[13578])|(1[02]))");
        reg.append("-?((0?[1-9])|([1-2][0-9])|(3[01])))|(((0?[469])|(11))");
        reg.append("-?((0?[1-9])|([1-2][0-9])|(30)))|(0?2-?((0?[");
        reg.append("1-9])|(1[0-9])|(2[0-8]))))))");
        Pattern p = Pattern.compile(reg.toString());
        return p.matcher(date).matches();
    }


    /*****
     * 时间 增加、减少 n个小时以后时间
     * @param d
     *          YYYY-mm-dd HH:mm:ss
     * @param num>0  小时
     * @param type  增加和减少标志
     * **/
    public static Date adjustDateByHour(Date d, Integer num, int type) {
        Calendar Cal = Calendar.getInstance();
        DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Cal.setTime(d);
        if (type == 0) {
            Cal.add(Calendar.MINUTE, -num);
            // System.out.println("date:"+df.format(Cal.getTime()));

        } else {
            Cal.add(Calendar.MINUTE, num);
            //System.out.println("date:"+df.format(Cal.getTime()));
        }
        return Cal.getTime();
    }

    /*****
     * 时间 增加、减少 n个分钟以后时间
     * @param d
     *          YYYY-mm-dd HH:mm:ss
     * @param num>0  分钟
     * @param type  增加和减少标志
     * **/
    public static Date adjustDateByMinutes(Date d, Integer num, int type) {
        Calendar Cal = Calendar.getInstance();
        DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Cal.setTime(d);
        if (type == 0) {
            Cal.add(Calendar.MINUTE, -num);
            //  System.out.println("date:"+df.format(Cal.getTime()));

        } else {
            Cal.add(Calendar.MINUTE, num);
            //   System.out.println("date:"+df.format(Cal.getTime()));
        }
        return Cal.getTime();
    }


    /*****
     * 比较当前时间是否在时间段内
     * @param date  需要比较的时间
     *          YYYY-mm-dd HH:mm:ss
     * @param start 开始时间
     *          HH:mm:ss
     * @param end  结束时间
     *          HH:mm:ss
     * **/
    public static Boolean isInTime(Date date, String start, String end) {
        if (date == null || start == null || start.isEmpty() || end == null || end.isEmpty()) {
            return false;
        }
        if (start.length() == 5) {
            start = start + ":00";
        }
        if (start.length() == 4) {
            start = "0" + start + ":00";
        }
        if (end.length() == 5) {
            end = end + ":00";
        }
        if (end.length() == 4) {
            end = "0" + end + ":00";
        }
        System.out.println("==========================start:" + start + "," + "end:" + end + ",now:" + DateUtil.format(date, DateUtil.FORMAT_ONE));
        String taskTime = DateUtil.format(date, "HH:mm:ss");
        String preDate = DateUtil.format(new Date(), DateUtil.LONG_DATE_FORMAT);
        Date taskDate = stringtoDate(preDate + " " + taskTime, DateUtil.FORMAT_ONE);
        Date startDate = stringtoDate(preDate + " " + start, DateUtil.FORMAT_ONE);
        Date endDate = stringtoDate(preDate + " " + end, DateUtil.FORMAT_ONE);
        //Date todayLastDate = stringtoDate(preDate+" 23:59:59", DateUtil.FORMAT_ONE);
        if (startDate == null || endDate == null) {
            return false;
        }
        if (startDate.after(endDate)) {
            if (taskDate.after(startDate)) {
                return true;
            }
            if (taskDate.before(endDate)) {
                return true;
            }
        } else {
            if (taskDate.after(startDate) && taskDate.before(endDate)) {
                return true;
            }
        }
        return false;
        /*if(endDate.before(startDate)){
            Calendar calendar = Calendar.getInstance();
            calendar.setTime(endDate);
            calendar.add(calendar.DATE,1);//把日期往后增加一天.整数往后推,负数往前移动
            endDate = calendar.getTime();
        }
        if(date.after(startDate) && date.before(endDate)){
            return true;
        }else{
            return false;
        }*/
    }

    public static Date parse(String string) {
        try {
            return DateUtils.parseDateStrictly(string, new String[]{DATE_FORMATE_STRING_A, FORMAT_ONE, FORMAT_TWO, FORMAT_THREE, FORMAT_FOUR_MINUTE});
        } catch (ParseException var2) {
            LOGGER.warn("解析日期时出现了错误：" + string);
            return null;
        }
    }

    /**
     * 毫秒数转为时分秒
     * @param ms
     * @return
     */
    public static String parseHHMMSS(Long ms){
        SimpleDateFormat formatter = new SimpleDateFormat("HH:mm:ss");//这里想要只保留分秒可以写成"mm:ss"
        formatter.setTimeZone(TimeZone.getTimeZone("GMT+00:00"));
        String hms = formatter.format(ms);
        System.out.println(hms);
        return hms;
    }


    public static String getDatePoor(Date endDate, Date nowDate) {

        long nd = 1000 * 24 * 60 * 60;
        long nh = 1000 * 60 * 60;
        long nm = 1000 * 60;
        // long ns = 1000;
        // 获得两个时间的毫秒时间差异
        long diff = endDate.getTime() - nowDate.getTime();
        // 计算差多少天
        long day = diff / nd;
        // 计算差多少小时
        long hour = diff % nd / nh;
        // 计算差多少分钟
        long min = diff % nd % nh / nm;
        // 计算差多少秒//输出结果
        // long sec = diff % nd % nh % nm / ns;
        return String.valueOf(day * 24 * 60 * 60 + hour * 60 * 60 + min * 60);
//        return day + "天" + hour + "小时" + min + "分钟";
    }

    public static String getDateMs(Date endDate, Date nowDate) {

        double nd = 1000 * 24 * 60 * 60;
        double nh = 1000 * 60 * 60;
        double nm = 1000 * 60;
        // long ns = 1000;
        // 获得两个时间的毫秒时间差异
        double diff = endDate.getTime() - nowDate.getTime();
        // 计算差多少天
        double day = Math.round((diff / nd < 1 ? 0.0 : (diff / nd)) * 10) / 10;
        // 计算差多少小时
        double hour = Math.round((diff % nd / nh) * 10) / 10;
        // 计算差多少分钟
        double min = Math.round((diff % nd % nh / nm) * 10) / 10;
        // 计算差多少秒//输出结果
        // long sec = diff % nd % nh % nm / ns;
        return String.valueOf(day * 24 * 60 * 60 + hour * 60 * 60 + min * 60);
//        return day + "天" + hour + "小时" + min + "分钟";
    }

    /**
     * 获取两个日期间隔的所有日期
     *
     * @param start 格式必须为'2018-01-25'
     * @param end   格式必须为'2018-01-25'
     * @return
     */
    public static List<String> getBetweenDate(String start, String end) {
        LocalDate startDate = LocalDate.parse(start);
        LocalDate endDate = LocalDate.parse(end);
        return getBetweenDate(startDate, endDate);
    }

    public static List<String> getBetweenDate(Date start, Date end) {
        ZoneId zone = ZoneId.systemDefault();

        LocalDateTime startDateTime = LocalDateTime.ofInstant(start.toInstant(), zone);
        LocalDateTime endDateTime = LocalDateTime.ofInstant(end.toInstant(), zone);
        return getBetweenDate(startDateTime.toLocalDate(), endDateTime.toLocalDate());
    }

    public static List<String> getBetweenDate(LocalDate start, LocalDate end) {
        List<String> list = new ArrayList<>();
        long distance = ChronoUnit.DAYS.between(start, end);
        if (distance < 1) {
            return list;
        }
        Stream.iterate(start, d -> d.plusDays(1)).limit(distance + 1).forEach(f -> list.add(f.toString()));
        return list;
    }

    public static Date dateMinusDay(){
        Date now = now();
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(now);
        calendar.add(Calendar.DATE,-1);
        return calendar.getTime();
    }

    public static void main(String[] args) {
//    	String dateStr = DateUtil.yearthDate("2017-05-30");
//    	System.out.println(dateStr);
//    	long min = DateUtil.timeSub("2017-04-12 00:00:00", "2017-04-13 00:00:00")/60;
//    	System.out.println(min);
        /*String settlementDate = DateUtil.dateToString(new Date(), "yyyy-MM-dd");
        long day = DateUtil.dayDiff(DateUtil.stringtoDate("2017-06-22", "yyyy-MM-dd"),DateUtil.stringtoDate(settlementDate, "yyyy-MM-dd"));
        if(day >= 0){
            System.out.println(day);
        }

        String goodsArriveTime = "2017-04-02 17:00-18:00";
        int space_index = goodsArriveTime.indexOf(" ");
        String arrive_date = goodsArriveTime.substring(0, space_index);
        String arrive_time = goodsArriveTime.substring(space_index+1, goodsArriveTime.length());

        System.out.println(arrive_date);
        System.out.println(arrive_time);
        String arrive_start_time = arrive_time.substring(0, 2);
        String arrive_end_time = arrive_time.substring(6,8);

        System.out.println(arrive_start_time);
        System.out.println(arrive_end_time);

        String Time = DateUtil.getCurrDate("HH");
        System.out.println(Time);

        String Time2 = DateUtil.getCurrDate("mm");
        System.out.println(Time2);*/
//        System.out.println(isInTime(new Date(), "08:00:00", "3:00:00"));

//        System.out.println(getDistanceDays(dateToString(new Date(),"yyyy-MM-dd HH:mm:ss"),"2019-04-21 19:24:33"));
//        System.out.println(Double.parseDouble(getDateMs(stringtoDate("2019-07-09 23:31:33", "yyyy-MM-dd HH:mm:ss"), stringtoDate("2019-07-09 00:00:00", "yyyy-MM-dd HH:mm:ss"))) / 60);
        System.out.println(String.valueOf(dateMinusDay()));


    }

}
